package com.qumitech.visualnovel.service.content.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.exception.BusinessException;
import com.qumitech.visualnovel.component.util.DateUtil;
import com.qumitech.visualnovel.component.util.HttpInvokeUtil;
import com.qumitech.visualnovel.model.common.BaseRsp;
import com.qumitech.visualnovel.model.common.ResultEnum;
import com.qumitech.visualnovel.model.common.BaseResponse;
import com.qumitech.visualnovel.datasource.console.SpiderArticleMapper;
import com.qumitech.visualnovel.datasource.console.SpiderCommentMapper;
import com.qumitech.visualnovel.model.dao.console.SpiderArticleWithBLOBs;
import com.qumitech.visualnovel.model.dao.console.SpiderComment;
import com.qumitech.visualnovel.model.common.UrlConstant;
import com.qumitech.visualnovel.service.content.ContentDeliveryService;
import com.qumitech.visualnovel.service.robot.RobotService;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;


@Service
public class ContentDeliveryServiceImpl implements ContentDeliveryService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private static final String TOPIC_OPTION_URL = "/trend/console/all_topics";

    private static final String PUBLISH_CONTENT_URL = "/robot/trend/";

    private static final String TOPIC_OPTION_DELETE_URL =  "/robot/trend/remove";

    @Autowired
    SpiderArticleMapper spiderArticleMapper;

    @Autowired
    SpiderCommentMapper spiderCommentMapper;
    @Autowired
    RobotService robotService;

    // @Value("${app.niub.getToken}")
    private String tokenUrl;

    // @Value("${app.qiniu.domin}")
    private String iconUrl;

    @Autowired
    private DateUtil dateUtil;

    @Override
    public List<SpiderArticleWithBLOBs> getList(Integer sourceType, String subType, Integer spiderId, Integer checked,
                                                Integer hasImage,Integer hasVideo,  String startTime, String endTime,
                                                Integer offset, Integer limit, String orderType, String orderBy) {
        return spiderArticleMapper.getList(sourceType, subType, spiderId, checked, hasImage, hasVideo, startTime, endTime, offset, limit, orderType, orderBy);
    }

    @Override
    public Integer getCount(Integer sourceType,String subType, Integer spiderId, Integer checked, Integer hasImage, Integer hasVideo, String startTime, String endTime) {
        return spiderArticleMapper.getCount(sourceType, subType, spiderId, checked, hasImage, hasVideo, startTime, endTime);
    }

    @Override
    public List<SpiderArticleWithBLOBs> getRecommendList(Integer sourceType,Integer spiderId, Integer checked, Integer hasImage, Integer hasVideo, String startTime, String endTime, Integer offset, Integer limit, String orderType, String orderBy) {
        return spiderArticleMapper.getRecommendList(sourceType, spiderId, checked, hasImage, hasVideo, startTime, endTime, offset, limit, orderType, orderBy);
    }

    @Override
    public Integer getRecommendCount(Integer sourceType, Integer spiderId, Integer checked, Integer hasImage, Integer hasVideo, String startTime, String endTime) {
        return spiderArticleMapper.getRecommendCount(sourceType, spiderId, checked, hasImage, hasVideo, startTime, endTime);
    }

    @Override
    public String uploadImage(InputStream file){
        String result = "";
        JSONObject postData = new JSONObject();
        postData.put("bucket_name","im-picture");
        postData.put("deadline",120);
        String body = HttpInvokeUtil.httpPostJson(tokenUrl, postData, UrlConstant.DefaultEncode, null);
        if (body == null || body.equals(""))
        {
            throw new BusinessException(ResultEnum.FAILURE);
        }
        JSONObject rsp = JSONObject.parseObject(body);

        String token = rsp.getString("result");
        Configuration cfg = new Configuration(Zone.zone2());
        UploadManager uploadManager = new UploadManager(cfg);
        try{
            Response response = uploadManager.put(file, null, token,null, null);
            DefaultPutRet putRet =  JSON.parseObject(response.bodyString(), DefaultPutRet.class);
            result = iconUrl+putRet.key;
        }catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
        return result;
    }

    @Override
    public JSONArray getTopicOptions() {
        String body = HttpInvokeUtil.httpGet(UrlConstant.SERVER_URL + TOPIC_OPTION_URL, null,null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState() || rsp.getData() == null) {
            throw new BusinessException(ResultEnum.FAILURE);
        }
        JSONArray items = new JSONArray();
        JSONArray datas = (JSONArray) rsp.getData();
        for(int i = 0; i < datas.size(); i++)
        {
            JSONObject data = datas.getJSONObject(i);
            String categoryName = data.getJSONObject("category").getString("name");
            JSONArray topics = data.getJSONArray("topics");
            for(int j = 0; j < topics.size(); j++)
            {
                JSONObject item = new JSONObject();
                item.put("id", topics.getJSONObject(j).getString("topic_id"));
                item.put("text", categoryName + "_" + topics.getJSONObject(j).getString("title"));
                items.add(item);
            }
        }
        return items;
    }

    public List<SpiderComment> getCommentList(Long articleId){
        return spiderCommentMapper.getListByArticleId(articleId);
    }

    private boolean pushToServer(SpiderArticleWithBLOBs spiderArticle, List<SpiderComment> comments)
    {
        JSONObject postData = new JSONObject();
        postData.put("content", spiderArticle.getContent());
        postData.put("publish_time", spiderArticle.getPublishTime());
        JSONArray imageArray =  JSONArray.parseArray(spiderArticle.getImages());
        JSONArray newImageArray =  new JSONArray();
        for(int i=0;i<imageArray.size();i++)
        {
            newImageArray.add(imageArray.getString(i).replace("http://imp.qumitech.com/","").replace("http://p.qumitech.com/", ""));
        }
        postData.put("images", newImageArray);
        postData.put("topic_id", spiderArticle.getTopicId());
        postData.put("robot_id", spiderArticle.getBindRobotId());
        JSONArray commentArray = new JSONArray();
        for(SpiderComment spiderComment: comments)
        {
            JSONObject comment = new JSONObject();
            comment.put("content", spiderComment.getContent());
            comment.put("timestamp", spiderComment.getPublishTime());
            commentArray.add(comment);
        }
        postData.put("comment_list", commentArray);
        postData.put("third_id", spiderArticle.getId());
        if(spiderArticle.getVideoUrls()==null || spiderArticle.getVideoUrls().compareTo("") == 0) {

            postData.put("video_picture", null);
            postData.put("video_url", null);
        }
        else {
            JSONObject videoUrls = JSONObject.parseObject(spiderArticle.getVideoUrls());
            postData.put("video_picture", videoUrls.getString("pre_image").replace("http://imp.qumitech.com/","").replace("http://p.qumitech.com/", ""));
            postData.put("video_url", videoUrls.getString("video_url").replace("http://imp.qumitech.com/","").replace("http://p.qumitech.com/", ""));
        }

        //添加视频
        logger.info("pushToServer post:" + JSONObject.toJSONString(postData));
        String body = HttpInvokeUtil.httpPostJson(UrlConstant.SERVER_URL + PUBLISH_CONTENT_URL, JSONObject.toJSONString(postData),UrlConstant.DefaultEncode, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp != null) {
            logger.info("pushToServer response:" + rsp.toString());
        }
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()) {
            return false;
        }
        return true;
    }

    private void buildArticleByParam(JSONObject param, SpiderArticleWithBLOBs spiderArticle)
    {
        Date publishTime = param.getDate("publishTime");
        Long bindRobotId=param.getLong("bindRobotId");
        String nickname = param.getString("nickname");
        String avater = param.getString("avater");
        Integer sex = param.getInteger("sex");
        String signature = param.getString("signature");
        String label = param.getJSONArray("label").toJSONString();
        String topicId = param.getString("topicId");
        String title = param.getString("title");
        String content = param.getString("content");
        JSONArray imageArray = param.getJSONArray("images");
        List<String> imageList = new ArrayList();
        for(int i=0;i<imageArray.size();i++)
        {
            imageList.add("\"" + imageArray.getJSONObject(i).getString("url") +"\"");
        }
        String images = imageList.toString();
        //String voiceUrl = param.getString("voiceUrl");
        //String videoUrl = param.getString("videoUrl");
        Integer readedCount = param.getInteger("readedCount");
        Integer repostCount = param.getInteger("repostCount");
        Integer commentCount = param.getInteger("commentCount");
        Integer likeCount = param.getInteger("likeCount");
        Integer hotCount = param.getInteger("hotCount");
        spiderArticle.setPublishTime(publishTime);
        spiderArticle.setBindRobotId(bindRobotId);
        spiderArticle.setNickname(nickname);
        spiderArticle.setAvater(avater);
        spiderArticle.setSex(sex);
        spiderArticle.setSignature(signature);
        spiderArticle.setLabel(label);
        spiderArticle.setTopicId(topicId);
        spiderArticle.setTitle(title);
        spiderArticle.setContent(content);
        spiderArticle.setImages(images);
        //spiderArticle.setVideoUrls(voiceUrl);
        //spiderArticle.setVideoUrls(videoUrl);
        spiderArticle.setReadedCount(readedCount);
        spiderArticle.setRepostCount(repostCount);
        spiderArticle.setCommentCount(commentCount);
        spiderArticle.setLikeCount(likeCount);
        spiderArticle.setHotCount(hotCount);
    }

    public JSONObject update(JSONObject param)
    {

        Long articleId=param.getLong("id");
        long uid = param.getLong("bindRobotId");
        BaseRsp rsp = robotService.getRobotAccountWithNull(uid);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()
                || rsp.getData() == null) {
            return new BaseResponse<>(-2, "请使用机器人账号");
        }
        if(rsp.getStatus() == ResultEnum.SUCCESS.getState()){
            JSONObject robot = (JSONObject) rsp.getData();
            Object robotInfo = robot.get("robot");
            if(StringUtils.isBlank(robotInfo.toString())){
                return new BaseResponse<>(-2, "请使用机器人账号");
            }
        }
        SpiderArticleWithBLOBs spiderArticle = spiderArticleMapper.selectByPrimaryKey(articleId);
        buildArticleByParam(param, spiderArticle);
        if (spiderArticleMapper.updateByPrimaryKeyWithBLOBs(spiderArticle) !=0)
        {
            spiderCommentMapper.deleteByArticleId(articleId);
            List<SpiderComment> comments = JSONArray.parseArray(param.getString("comments"), SpiderComment.class);
            if(comments.size()!=0)
                spiderCommentMapper.addComments(comments, spiderArticle.getId());

        } else {
            return new BaseResponse<>(-1, "error");
        }
        return new BaseResponse<>(0, "success");
    }

    public JSONObject addToRecommend(Long articleId)
    {
        SpiderArticleWithBLOBs spiderArticle = spiderArticleMapper.selectByPrimaryKey(articleId);
        List<SpiderComment> spiderCommentList = spiderCommentMapper.getListByArticleId(articleId);
        if(spiderArticle.getPublishTime().getTime() > System.currentTimeMillis())
        {
            //发布时间是未来的某一个时间，就加入到预推荐列表，定时取发布
            spiderArticle.setStatus(2);
        }
        else {
            //推给服务器
            if (!pushToServer(spiderArticle, spiderCommentList)) {
                logger.info("add to recommend failed: id=" + spiderArticle.getId());
                spiderArticle.setStatus(3); //推荐失败
            } else {
                spiderArticle.setStatus(1);
            }
        }
        spiderArticleMapper.updateByPrimaryKey(spiderArticle);
        return new BaseResponse<>(0, "success");
    }

    @Override
    public JSONObject delete(List<Long>articleIdList, boolean isRecommend) {
        if(!isRecommend) {
            spiderArticleMapper.deleteByIdList(articleIdList);
            spiderCommentMapper.deleteByArticleIdList(articleIdList);
            return new BaseResponse<>(0, "success");
        } else {
            JSONObject postData = new JSONObject();
            JSONArray articleIdArray = new JSONArray();
            for(Long articleId: articleIdList)
            {
                articleIdArray.add(articleId.toString());
            }
            postData.put("third_ids", articleIdArray);
            String body = HttpInvokeUtil.httpPostJson(UrlConstant.SERVER_URL + TOPIC_OPTION_DELETE_URL, JSONObject.toJSONString(postData),UrlConstant.DefaultEncode, null);
            BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
            if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()) {
                return new BaseResponse<>(-1, "error");
            } else {
                //移回到内容仓库
                spiderArticleMapper.updateByIdList(articleIdList);
            }
            return new BaseResponse<>(0, "success");
        }
    }

    @Override
    public JSONObject getRandomComment(Long articleId, Long publishTime) {
        List<SpiderComment> spiderCommentList = spiderCommentMapper.getListByArticleId(articleId);
        Random rand = new Random();
        List<JSONObject> commentList = new LinkedList();
        int i = 0;
        for(SpiderComment spiderComment: spiderCommentList)
        {
            JSONObject comment = new JSONObject();
            comment.put("id", spiderComment.getId());
            comment.put("content", spiderComment.getContent());
            if(i==0)
                comment.put("publishTime", publishTime + rand.nextInt(60)*1000);
            else
                comment.put("publishTime", publishTime + rand.nextInt(3600*3)*1000);
            i+=1;
            comment.put("status", 0);
            commentList.add(comment);
        }
        //排序
        commentList.sort(new Comparator<JSONObject>() {
            private static final String key="publishTime";
            public int compare(JSONObject a, JSONObject b) {
                Integer valA=a.getInteger(key);
                Integer valB=b.getInteger(key);
                return valB.compareTo(valA);
            }
        });
        JSONObject data = new JSONObject();
        data.put("publishTime",  publishTime);
        data.put("items",  JSONArray.parseArray(commentList.toString()));
        return new BaseResponse<>(0, "success", data);
    }

    @Override
    public List<SpiderArticleWithBLOBs> pushRecommendTask() {
        List<SpiderArticleWithBLOBs> spiderArticleWithBLOBsList = spiderArticleMapper.getPreRecommendList(dateUtil.getCurrentTime());
        for(SpiderArticleWithBLOBs spiderArticleWithBLOBs: spiderArticleWithBLOBsList) {
            logger.info("spiderArticleWithBLOBs:" + spiderArticleWithBLOBs.toString());
            addToRecommend(spiderArticleWithBLOBs.getId());
        }
        return null;
    }

    @Override
    public JSONObject getQuality(Integer sourceType, String startTime, String endTime, Integer offset, Integer limit) {
        List<HashMap<String,Object>> spiderStaticsTotal = spiderArticleMapper.getTotalQuality(sourceType, startTime, endTime);
        JSONArray total = new JSONArray();
        for(HashMap<String,Object> spiderStaticsMap: spiderStaticsTotal)
        {
            JSONObject item = new JSONObject();
            item.put("sourceType", spiderStaticsMap.get("type"));
            item.put("total", spiderStaticsMap.get("total"));
            item.put("noPic", spiderStaticsMap.get("no_pic"));
            item.put("hasPic", spiderStaticsMap.get("pic"));
            total.add(item);
        }
        List<HashMap<String,Object>> spiderStaticsList = spiderArticleMapper.getQuality(sourceType, startTime, endTime, offset, limit);
        JSONArray items = new JSONArray();
        for(HashMap<String,Object> spiderStaticsMap: spiderStaticsList)
        {
            JSONObject item = new JSONObject();
            item.put("targetDate", spiderStaticsMap.get("create_time"));
            item.put("sourceType", spiderStaticsMap.get("type"));
            item.put("subType", spiderStaticsMap.get("sub_type"));
            item.put("total", spiderStaticsMap.get("total"));
            item.put("noPic", spiderStaticsMap.get("no_pic"));
            item.put("hasPic", spiderStaticsMap.get("pic"));
            items.add(item);
        }
        int count = spiderArticleMapper.getQualityCount(sourceType, startTime, endTime);
        JSONObject data = new JSONObject();
        data.put("count", count);
        data.put("items", items);
        data.put("total", total);
        return new BaseResponse<>(0, "success", data);
    }

    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("robot","");
        Object result = jsonObject.get("robot");
        String resultStr = JSON.toJSONString(result);
        System.out.println(StringUtils.isBlank(resultStr));
        System.out.println(StringUtils.isBlank(result.toString()));
    }
}
